﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ComputerAI : MonoBehaviour {

    /// <summary>
    /// 当前出牌的牌型
    /// </summary>
    public CardType currentCardType = CardType.None;
    /// <summary>
    /// 当前出的牌
    /// </summary>
    public List<Card> SelectCards = new List<Card>();
   
    /// <summary>
    /// 自动选牌
    /// </summary>
    /// <param name="cards">当前的手上的牌</param>
    /// <param name="cardType">上一轮出牌的类型</param>
    /// <param name="weight">上一轮出牌的权重</param>
    /// <param name="length">上一轮出牌的长度</param>
    /// <param name="isBiggest">是否是最大的出牌者</param>
    public void SmartSelectCards(List<Card> cards,CardType cardType,int weight,int length,bool isBiggest)
    {
        cardType = isBiggest ? CardType.None : cardType;
        //设定当前应该出的牌型
        currentCardType = cardType;
        SelectCards.Clear();
        switch (cardType)
        {
            case CardType.None:
                //找最小出牌 并修改当前出牌类型
                SelectCards = FindSmallestCard(cards);                
                break;
            case CardType.Single:
                SelectCards = FindSingle(cards, weight);
                break;
            case CardType.Double:
                SelectCards = FindDouble(cards, weight);
                break;
            case CardType.Straight:
                SelectCards = FindStraight(cards, weight, length);
                if (SelectCards.Count == 0)
                {
                    SelectCards = FindBoom(cards, -1);//最小的炸弹开始找
                    currentCardType = CardType.Boom;
                }
                break;
            case CardType.DoubleStraight:
                SelectCards = FindDoubleStraight(cards, weight, length);
                if (SelectCards.Count == 0)
                {
                    SelectCards = FindBoom(cards, -1);
                    currentCardType = CardType.Boom;
                }
                break;
            case CardType.TripleStraight:
                SelectCards = FindTripleStraight(cards, weight, length);
                if (SelectCards.Count == 0)
                {
                    SelectCards = FindBoom(cards, -1);
                    currentCardType = CardType.Boom;
                }
                break;
            case CardType.Three:
                SelectCards = FindThree(cards, weight);
                break;
            case CardType.ThreeAndOne:
                SelectCards = FindThreeAndOne(cards, weight);
                break;
            case CardType.ThreeAndTwo:
                SelectCards = FindThreeAndTwo(cards, weight);
                if (SelectCards.Count == 0)
                {
                    SelectCards = FindBoom(cards, -1);
                    currentCardType = CardType.Boom;
                }
                break;
            case CardType.Boom:
                SelectCards = FindBoom(cards, weight);
                break;
            case CardType.JokerBoom:
                SelectCards = FindJokerBoom(cards);
                break;
            default:
                break;

        }
    }
    #region 查找方法
    private List<Card> FindSmallestCard(List<Card> cards)
    {
        List<Card> SelectCards = new List<Card>();
        //出顺子
        for (int i = 12; i >=5; i--)
        {
            SelectCards = FindStraight(cards, -1, i);
            if (SelectCards.Count != 0)
            {               
                currentCardType = CardType.Straight;//修改当前出牌类型
                break;
            }
        }
        //出双顺
        if (SelectCards.Count == 0)
        {
            for (int i = 20; i >= 6; i-=2)
            {
                SelectCards = FindDoubleStraight(cards, -1, i);
                if (SelectCards.Count != 0)
                {
                    currentCardType = CardType.DoubleStraight;
                    break;
                }
            }
        }
        //出三顺
        if (SelectCards.Count == 0)
        {
            for (int i = 18; i >= 6; i-=3)
            {
                SelectCards = FindTripleStraight(cards, -1, i);
                if (SelectCards.Count != 0)
                {
                    currentCardType = CardType.TripleStraight;
                    break;
                }
            }
        }
        //找三带二
        if (SelectCards.Count == 0)
        {
            for (int i = 0; i <= 36; i++)
            {
                SelectCards = FindThreeAndTwo(cards, i-1);
                if (SelectCards.Count != 0)
                {
                    currentCardType = CardType.ThreeAndTwo;
                    break;
                }
            }
        }
        //找三带一
        if (SelectCards.Count == 0)
        {
            for (int i = 0; i <= 36; i ++)
            {
                SelectCards = FindThreeAndOne(cards, i-1);
                if (SelectCards.Count != 0)
                {
                    currentCardType = CardType.ThreeAndOne;
                    break;
                }
            }
        }
        //找三不带
        if (SelectCards.Count == 0)
        {
            for (int i = 0; i <= 36; i ++)
            {
                SelectCards = FindThree(cards, i-1);
                if (SelectCards.Count != 0)
                {
                    currentCardType = CardType.Three;
                    break;
                }
            }
        }
        //找对
        if (SelectCards.Count == 0)
        {
            for (int i = 0; i <= 24; i += 2)
            {
                SelectCards = FindDouble(cards, i - 1);
                if (SelectCards.Count != 0)
                {
                    currentCardType = CardType.Double;
                    break;
                }
            }
        }
        //找单
        if (SelectCards.Count == 0)
        {
            SelectCards = FindSingle(cards,- 1);
            currentCardType = CardType.Single;
        }
        return SelectCards;
    }
    /// <summary>
    /// 选择单牌
    /// </summary>
    /// <param name="cards">当前手上的牌</param>
    /// <param name="weight">上一轮的牌的总权重</param>
    /// <returns></returns>
    private List<Card> FindSingle(List<Card> cards, int weight)
    {
        List<Card> SelectCards = new List<Card>();
        for (int i = 0; i < cards.Count; i++)
        {
            if ((int)cards[i].CardWeight > weight)
            {
                SelectCards.Add(cards[i]);
                break;
            }
        }
        return SelectCards;
    }
    /// <summary>
    /// 选择对儿
    /// </summary>
    /// <param name="cards">当前手中的牌</param>
    /// <param name="weight">上一轮的牌的总权重</param>
    /// <returns></returns>
    private List<Card> FindDouble(List<Card> cards, int weight)
    {
        List<Card> SelectCards = new List<Card>();
        for (int i = 0; i < cards.Count - 1; i++)
        {
            if (cards[i].CardWeight == cards[i + 1].CardWeight)
            {
                if ((int)cards[i].CardWeight * 2 > weight)
                {
                    SelectCards.Add(cards[i]);
                    SelectCards.Add(cards[i + 1]);
                    break;
                }
            }
        }
        return SelectCards;
    }
    /// <summary>
    /// 查找顺子
    /// </summary>
    /// <param name="cards">当前手上的牌</param>
    /// <param name="weight">上一轮的权重</param>
    /// <param name="length">上一轮的长度</param>
    /// <returns></returns>
    private List<Card> FindStraight(List<Card> cards, int weight, int length)
    {
        List<Card> SelectCards = new List<Card>();
        List<int> indexList = new List<int>();
        int counter = 0;
        //45678
        for (int i = 0; i < cards.Count - 4; i++)//在至少5张牌
        {
            if ((int)cards[i].CardWeight > weight)
            {
                counter = 1;
                indexList.Clear();
                indexList.Add(i);
                for (int j = i + 1; j < cards.Count; j++)
                {
                    if (cards[j].CardWeight > Weight.One)
                        break;
                    if ((int)cards[j].CardWeight - (int)cards[i].CardWeight == counter)
                    {
                        counter++;
                        indexList.Add(j);
                    }
                    if (counter == length)//找到相应的长度
                        break;
                }
            }
            if (counter == length)//找到相应的长度
            {
                // indexList.Insert(0, i);
                break;
            }
        }
        if (counter == length)
        {
            for (int i = 0; i < indexList.Count; i++)
            {
                SelectCards.Add(cards[indexList[i]]);
            }
        }
        return SelectCards;
    }
    /// <summary>
    /// 找双顺
    /// </summary>
    /// <param name="cards">手中的牌</param>
    /// <param name="weight">上一轮的权重</param>
    /// <param name="length">上一轮的长度</param>
    /// <returns></returns>
    private List<Card> FindDoubleStraight(List<Card> cards, int weight, int length)
    {
        List<Card> SelectCards = new List<Card>();
        List<int> indexList = new List<int>();
        int counter = 0;
        //445566
        for (int i = 0; i < cards.Count - 5; i++)//在至少6张牌
        {
            if ((int)cards[i].CardWeight > weight && cards[i].CardWeight == cards[i + 1].CardWeight)
            {
                counter = 1;
                indexList.Clear();
                indexList.Add(i);
                indexList.Add(i + 1);
                for (int j = i + 2; j < cards.Count-1; j += 2)
                {
                    if (cards[j].CardWeight > Weight.One)
                        break;
                    if ((int)cards[j].CardWeight - (int)cards[i].CardWeight == counter
                        && (int)cards[j + 1].CardWeight - (int)cards[i].CardWeight == counter)
                    {
                        counter++;
                        indexList.Add(j);
                        indexList.Add(j + 1);
                    }
                    if (counter == length)//找到相应的长度
                        break;
                }
            }
            if (counter == length)//找到相应的长度
            {
                // indexList.Insert(0, i);
                break;
            }
        }
        if (counter == length)
        {
            for (int i = 0; i < indexList.Count; i++)
            {
                SelectCards.Add(cards[indexList[i]]);
            }
        }
        return SelectCards;
    }
    /// <summary>
    /// 找飞机
    /// </summary>
    /// <param name="cards">手中的牌</param>
    /// <param name="weight">上一轮的权重</param>
    /// <param name="length">上一轮的长度</param>
    /// <returns></returns>
    private List<Card> FindTripleStraight(List<Card> cards, int weight, int length)
    {
        List<Card> SelectCards = new List<Card>();
        List<int> indexList = new List<int>();
        int counter = 0;
        //444555
        for (int i = 0; i < cards.Count - 5; i++)//在至少6张牌
        {
            if ((int)cards[i].CardWeight > weight
                && cards[i].CardWeight == cards[i + 1].CardWeight
                && cards[i].CardWeight == cards[i + 2].CardWeight)
            {
                counter = 1;
                indexList.Clear();
                indexList.Add(i);
                indexList.Add(i + 1);
                indexList.Add(i + 2);
                for (int j = i + 3; j < cards.Count-3; j += 3)
                {
                    if (cards[j].CardWeight > Weight.One)
                        break;
                    if ((int)cards[j].CardWeight - (int)cards[i].CardWeight == counter
                        && (int)cards[j + 1].CardWeight - (int)cards[i].CardWeight == counter
                        && (int)cards[j + 2].CardWeight - (int)cards[i].CardWeight == counter)
                    {
                        counter++;
                        indexList.Add(j);
                        indexList.Add(j + 1);
                        indexList.Add(j + 2);
                    }
                    if (counter == length)//找到相应的长度
                        break;
                }
            }
            if (counter == length)//找到相应的长度
            {
                // indexList.Insert(0, i);
                break;
            }
        }
        if (counter == length)
        {
            for (int i = 0; i < indexList.Count; i++)
            {
                SelectCards.Add(cards[indexList[i]]);
            }
        }
        return SelectCards;
    }
    /// <summary>
    /// 找三不带
    /// </summary>
    /// <param name="cards">手上的牌</param>
    /// <param name="weight">上一轮的权重</param>
    /// <returns></returns>
    private List<Card> FindThree(List<Card> cards, int weight)
    {
        List<Card> SelectCards = new List<Card>();

        for (int i = 0; i < cards.Count - 2; i++)//至少3张牌
        {
            if ((int)cards[i].CardWeight > weight)
            {
                if (cards[i].CardWeight == cards[i + 1].CardWeight &&
                    cards[i].CardWeight == cards[i + 2].CardWeight)
                {
                    SelectCards.Add(cards[i]);
                    SelectCards.Add(cards[i + 1]);
                    SelectCards.Add(cards[i + 2]);
                }
            }
            if (SelectCards.Count == 3)//找到了就跳出
                break;
        }

        return SelectCards;
    }
    /// <summary>
    /// 找三带一
    /// </summary>
    /// <param name="cards">手中的牌</param>
    /// <param name="weight">上一轮的权重</param>
    /// <returns></returns>
    private List<Card> FindThreeAndOne(List<Card> cards, int weight)
    {
        List<Card> SelectCards = new List<Card>();
        List<int> indexList = new List<int>();
        int minWeight = -1;//找单牌从权值最小开始找
        for (int i = 0; i < cards.Count - 3; i++)//至少4张牌
        {
            if ((int)cards[i].CardWeight > weight)
            {
                if (cards[i].CardWeight == cards[i + 1].CardWeight &&
                    cards[i].CardWeight == cards[i + 2].CardWeight)
                {
                    SelectCards.Add(cards[i]);
                    SelectCards.Add(cards[i + 1]);
                    SelectCards.Add(cards[i + 2]);
                    indexList.Add(i);
                    indexList.Add(i + 1);
                    indexList.Add(i + 2);
                }
            }
            if (SelectCards.Count == 3)//找到了就跳出
                break;
        }
        if (SelectCards.Count == 0)
            return SelectCards;
        for (int i = 0; i < cards.Count; i++)
        {
            minWeight++;
            if (indexList.Contains(i))//判断是否是找到的三张相同需要的牌
                break;
            if ((int)cards[i].CardWeight == minWeight)
            {
                SelectCards.Add(cards[i]);
                break;
            }
        }
        if (SelectCards.Count == 3)
            SelectCards.Clear();
        return SelectCards;
    }
    /// <summary>
    /// 找三带二
    /// </summary>
    /// <param name="cards">手中的牌</param>
    /// <param name="weight">上一轮的权值</param>
    /// <returns></returns>
    private List<Card> FindThreeAndTwo(List<Card> cards, int weight)
    {
        List<Card> SelectCards = new List<Card>();
        List<int> indexList = new List<int>();
        int minWeight = -1;//找单牌从权值最小开始找
        for (int i = 0; i < cards.Count - 4; i++)//至少5张牌
        {
            if ((int)cards[i].CardWeight > weight)
            {
                if (cards[i].CardWeight == cards[i + 1].CardWeight &&
                    cards[i].CardWeight == cards[i + 2].CardWeight)
                {
                    SelectCards.Add(cards[i]);
                    SelectCards.Add(cards[i + 1]);
                    SelectCards.Add(cards[i + 2]);
                    indexList.Add(i);
                    indexList.Add(i + 1);
                    indexList.Add(i + 2);
                }
            }
            if (SelectCards.Count == 3)//找到了就跳出
                break;
        }
        if (SelectCards.Count == 0)
            return SelectCards;
        for (int i = 0; i < cards.Count-1; i++)
        {
            minWeight++;
            if (indexList.Contains(i))//判断是否是找到的三张相同需要的牌
                break;
            if (cards[i].CardWeight == cards[i + 1].CardWeight)
            {
                if ((int)cards[i].CardWeight == minWeight)
                {
                    SelectCards.Add(cards[i]);
                    SelectCards.Add(cards[i+1]);
                    break;
                }
            }
        }
        if (SelectCards.Count == 3)
            SelectCards.Clear();
        return SelectCards;
    }
    /// <summary>
    /// 找炸弹
    /// </summary>
    /// <param name="cards">手中的牌</param>
    /// <param name="weight">上一轮的权重</param>
    /// <returns></returns>
    private List<Card> FindBoom(List<Card> cards, int weight)
    {
        List<Card> SelectCards = new List<Card>();
        for (int i = 0; i < cards.Count - 3; i++)
        {
            //普通炸弹
            if (cards[i].CardWeight == cards[i + 1].CardWeight
                && cards[i].CardWeight == cards[i + 2].CardWeight
                && cards[i].CardWeight == cards[i + 3].CardWeight)
            {
                int totalWeight = (int)cards[i].CardWeight + (int)cards[i + 1].CardWeight + (int)cards[i + 2].CardWeight + (int)cards[i + 3].CardWeight;
                if (totalWeight > weight)
                {
                    SelectCards.Add(cards[i]);
                    SelectCards.Add(cards[i + 1]);
                    SelectCards.Add(cards[i + 2]);
                    SelectCards.Add(cards[i + 3]);
                    break;
                }
            }

        }
        //王炸
        SelectCards = FindJokerBoom(cards);
        return SelectCards;
    }
    /// <summary>
    /// 找王炸
    /// </summary>
    /// <param name="cards"></param>
    /// <returns></returns>
    private List<Card> FindJokerBoom(List<Card> cards)
    {
        List<Card> SelectCards = new List<Card>();
        for (int i = 0; i < cards.Count - 1; i++)
        {
            //王炸
            if (cards[i].CardWeight == Weight.SJoker && cards[i + 1].CardWeight == Weight.LJoker)
            {
                SelectCards.Add(cards[i]);
                SelectCards.Add(cards[i + 1]);
                break;
            }
        }
        currentCardType = CardType.JokerBoom;
        return SelectCards;
    } 
    #endregion
}
